import Head from 'next/head';
import SimpleCodeSandbox from '../../../examples/SimpleCodeSandbox';

<Head>
  <title>{'Usage - Mantine React Table V2 Docs'}</title>
  <meta
    name="description"
    content="A brief overview of how to use mantine-react-table and create columns and data"
  />
</Head>

## Usage

Here is a brief overview of how to use Mantine React Table. This is a very simple example and will not cover all features of the library, but should be a great starting point.

### Setup

To start using MantineReactTable, you first need to [install](/docs/getting-started/install) `mantine-react-table` and the necessary Mantine dependencies.

There are additional steps and customizations you can do with your Mantine Theme, if you have not set it up in your application already. Check out the [Mantine docs](https://mantine.dev/theming/theme-object/) for more information.

If you need to change the colors of the table components, advanced [Mantine Theming](https://mantine.dev/theming/mantine-provider/) is covered in the [Customize Components](/docs/guides/customize-components) guide.

### Import MantineReactTable and useMantineReactTable

Once you have everything installed, you can import from `mantine-react-table` like this:

```tsx
import { MantineReactTable, useMantineReactTable } from 'mantine-react-table';
```

`MantineReactTable` is the main component that you will use to render your table.

`useMantineReactTable` is the React hook that you will use to define all the columns, data, and other options for your table.

### Creating Data/Rows

Your data must be an array of objects that have properties matching the accessors in your column definitions. The objects themselves can theoretically be in any shape, but it will be easier to set up your columns if your data is already in a flat object format like the example below, but it is not required.

> **Common Gotcha**: When defining `data` that will be passed to a `useMantineReactTable` hook, make sure that the `data` is _memoized_ or _stable_ (i.e. `useState`, `useMemo`, defined outside of your table component, etc.). Otherwise you may get infinite renders.

#### Simple Data Example

```jsx
//recommended flat structure for data, but not required (nested data is fine, but takes more setup in column definitions)
//must be memoized or stable (useState, useMemo, defined outside of the component, etc.)
const data = [
  {
    name: 'John', // key "name" matches `accessorKey` in ColumnDef down below
    age: 30, // key "age" matches `accessorKey` in ColumnDef down below
  },
  {
    name: 'Sara',
    age: 25,
  },
];
```

Your data does NOT have to be created statically like this, of course. More than likely, your data is being fetched from a backend API. Check out the [Remote Data examples](/docs/examples/react-query) to see how you can fetch data and pass it to your tables.

### Creating Columns

There are several different ways to define columns, depending on your needs. Let's create some basic `"data"` columns. That is, columns that connect to our data. Most of the time, we can simply use the `accessorKey` property to access the data if the data is in a simple format. Alternatively, if some data in a column needs some logic or processing, you can use the `accessorFn` property to define a function that returns the data for each cell.

#### Simple Column Definition Example

```jsx
//simple column definitions pointing to flat data
const columns = useMemo(
  () => [
    {
      header: 'Name',
      accessorKey: 'name', //simple recommended way to define a column
      //more column options can be added here to enable/disable features, customize look and feel, etc.
      //optional custom cell render
      Cell: ({ row }) => (
        <Box style={{ display: 'flex', gap: '2ch', alignItems: 'center' }}>
          <img src={row.original.imageUrl} />
          <a href={row.profileUrl}>{row.name}</a>
        </Box>
      ),
    },
    {
      header: 'Age',
      accessorFn: (dataRow) => parseInt(dataRow.age), //alternate way to access data if processing logic is needed
    },
  ],
  [],
);
```

> Note: Do NOT have your accessors resolve JSX or markup. That's what custom `Cell` renders are for. Accessors should only return primitive data so that the table can sort, filter, search, and group properly.

### Full Simple Example

Put it all together, and you have a basic table! You can also play around and enable some features, either per column in the column definitions, or as table options passed to `useMantineReactTable`.

```tsx
import { useMemo } from 'react';
import {
  MantineReactTable,
  useMantineReactTable,
  type MRT_ColumnDef, //if using TypeScript (optional, but recommended)
} from 'mantine-react-table';

//If using TypeScript, define the shape of your data (optional, but recommended)
interface Person {
  name: string;
  age: number;
}

//mock data - strongly typed if you are using TypeScript (optional, but recommended)
const data: Person[] = [
  {
    name: 'John',
    age: 30,
  },
  {
    name: 'Sara',
    age: 25,
  },
];

export default function App() {
  //column definitions - strongly typed if you are using TypeScript (optional, but recommended)
  const columns = useMemo<MRT_ColumnDef<Person>[]>(
    () => [
      {
        accessorKey: 'name', //simple recommended way to define a column
        header: 'Name',
        mantineTableHeadCellProps: { style: { color: 'green' } }, //custom props
        enableHiding: false, //disable a feature for this column
      },
      {
        accessorFn: (originalRow) => originalRow.age, //alternate way
        id: 'age', //id required if you use accessorFn instead of accessorKey
        header: 'Age',
        Header: <i style={{ color: 'red' }}>Age</i>, //optional custom markup
      },
    ],
    [],
  );

  //pass table options to useMantineReactTable
  const table = useMantineReactTable({
    columns,
    data, //must be memoized or stable (useState, useMemo, defined outside of this component, etc.)
    enableRowSelection: true, //enable some features
    enableColumnOrdering: true, //enable a feature for all columns
    enableGlobalFilter: false, //turn off a feature
  });

  //note: you can also pass table options as props directly to <MantineReactTable /> instead of using useMantineReactTable
  //but the useMantineReactTable hook will be the most recommended way to define table options
  return <MantineReactTable table={table} />;
}
```

> **Note:** Again, it is very important that the columns and data definitions are _memoized_ or _stable_. Otherwise, the entire table will be re-rendered during every react re-render in your application, which can lead to performance issues. To make a variable stable, store it in `useState`, wrap it in `useMemo`, define it outside of a component, or in your state management tool of choice so it does not get recreated on every render and cause an infinite re-render loop.

### Live Code Sandbox Example

<SimpleCodeSandbox />

### Next Steps

There are numerous ways you can customize the behavior and look and feel of your Mantine React Table. View some of the [examples](/docs/examples) to see how you can customize your table, and visit the [props page](/docs/api/table-options) to see all the props that you can use to turn features on and off and customize the look and feel of your table.

Also, be sure to check out all the [Fundamental Guides](/docs/guides#fundamentals) and any of the [Advanced Feature Guides](/docs/guides#feature-guides) you may be interested in to learn more about the different features you can toggle on and off, or customize.
